import * as cc from "cc";
import LevelManager from "./LevelManager";
import { GlobalEnum } from "../../Script/GameSpecial/GlobalEnum";
import { EventType } from "../../Script/GameSpecial/GameEventType";
import GlobalPool, { customPoolScript } from "../../Script/Common/GlobalPool";
import LevelCamera from "./LevelCamera";
import GlobalData from "../../Script/Common/GlobalData";
import PlayerData from "../../Script/Common/PlayerData";
import { Player } from "../../Role/Script/Player";
import { Enemy } from "../../Role/Script/Enemy";
import AIManager from "./AIManager";
import LevelColler from "../../MainScene/Script/LevelColler";
import GameData from "../../Script/Common/GameData";
import CollerManager from "./CollerManager";
import { GoldItem } from "../../LevelColler/Script/GoldItem";
import AtkBox from "../../Role/Script/AtkBox";
import yyComponent from "../../Script/Common/yyComponent";
import { Trapper } from "../../Weapon/Script/Trapper";
import { Role } from "../../Role/Script/Role";
import { Portal } from "../../LevelColler/Script/Portal";

const { ccclass, property } = cc._decorator;

@ccclass
export default class MyLevelManager extends LevelManager {

    /**************************************************通用流程**************************************************/
    //#region 
    public init() {
        this.initActMng();
        this.initAtkBox();
        this.initBodyLayer();
        this.initBoom();
        this.initBreakAnims();
        this.initBreakBarrier();
        this.initCamera();
        this.initCollMng();
        this.initColliderLayer();
        this.initCustomUpdateState();
        this.initDynamicBarrier();
        this.initEnemies();
        this.initEnterLobbyState();
        this.initGold();
        this.initGrade();
        this.initLevelTimer();
        this.initMap();
        this.initParticle();
        this.initPlayer();
        this.initPortal();
        this.initScanBox();
        this.initStaticBarrier();
        this.initTrappers();

        this.loadLobbyItems();

        this.registAllCustomUpdate();
        this.onEvents();

    }
    protected registAllCustomUpdate() {
        //通用状态
        this.registCustomUpdate(GlobalEnum.LevelState.waitTrySkin, this.stepWaitTrySkin);
        this.registCustomUpdate(GlobalEnum.LevelState.playing, this.stepLevelPlaying);
        this.registCustomUpdate(GlobalEnum.LevelState.win, this.stepLevelWin);
        this.registCustomUpdate(GlobalEnum.LevelState.lose, this.stepLevelLose);
        this.registCustomUpdate(GlobalEnum.LevelState.lobby, this.stepLobby);
        this.registCustomUpdate(GlobalEnum.LevelState.fighting, this.stepPlayerFighting);
        this.registCustomUpdate(GlobalEnum.LevelState.teaching, this.stepTeaching);

        //其他状态
    }
    protected onEvents() {
        //游戏总流程相关
        this.on(EventType.Common.DirectorEvent.pauseLevel, this.pause, this);
        this.on(EventType.Common.DirectorEvent.resumeLevel, this.resume, this);
        this.on(EventType.Common.TeachEvents.teachFinish, this.onTeachFinish, this);
        this.on(EventType.myTeachEvent.addPortals, this.onAddPortal, this);

        this.on(EventType.LevelEvent.testLose, this.onTestLose, this);
        this.on(EventType.LevelEvent.testWin, this.onTestWin, this);

        this.on(EventType.LevelEvent.resurgence, this.onResurgence, this);

        //游戏玩法相关
        //玩家
        this.on(EventType.LevelEvent.killPlayer, this.onPlayerDead, this);
        this.on(EventType.LevelEvent.playerDeadAnimFinished, this.onPlayerDeadAnimFinished, this);
        //2D物理节点
        this.on(EventType.LevelEvent.addRigidNode, this.onAddRigidNode, this);
        //障碍物
        this.on(EventType.LevelEvent.removeBreakBarrier, this.onRemoveBreakBarrier, this);
        this.on(EventType.LevelEvent.removeDynamicBarrier, this.onRemoveDynamicBarrier, this);
        this.on(EventType.LevelEvent.addBreakAnim, this.onAddBreakAnim, this);
        this.on(EventType.LevelEvent.removeBreakAnim, this.onRemoveBreakAnim, this);
        //金币
        this.on(EventType.LevelEvent.dropGold, this.onDropGold, this);
        this.on(EventType.LevelEvent.addGoldColler, this.onAddGoldColler, this);
        this.on(EventType.LevelEvent.getGold, this.onGetGold, this);
        this.on(EventType.LevelEvent.removeGold, this.onRemoveGold, this);
        //攻击框
        this.on(EventType.LevelEvent.addAtkBox, this.onAddAtkBox, this);
        this.on(EventType.LevelEvent.removeAtkBox, this.onRemoveAtkBox, this);
        //敌人
        this.on(EventType.LevelEvent.playerKillEnemy, this.onPlayerKillEnemy, this);
        this.on(EventType.LevelEvent.enemyDead, this.onEnemyDead, this);
        //尸体
        this.on(EventType.LevelEvent.addDeadBody, this.onAddDeadBody, this);
        this.on(EventType.LevelEvent.deadAnimFinish, this.onDeadAnimFinish, this);
        //无敌特效
        this.on(EventType.LevelEvent.addScanBox, this.onAddScanBox, this);
        //粒子特效
        this.on(EventType.LevelEvent.addParticle, this.onAddParticle, this);
        //皮肤试用
        this.on(EventType.LevelEvent.decideWeaponSkin, this.onDecideSkin, this);
        this.on(EventType.LevelEvent.changePlayerSkin, this.onChangePlayerSkin, this);
        //炸弹
        this.on(EventType.LevelEvent.addTrapper, this.addTrapper, this);
        this.on(EventType.LevelEvent.removeTrapper, this.removeTrapper, this);
        this.on(EventType.LevelEvent.addBoomEffect, this.addBoom, this);
    }
    /**加载进入首页时必须显示的内容 */
    protected loadLobbyItems() {

    }
    public reset() {
        this.resetAtkBox();
        this.resetBodyLayer();
        this.resetBoom();
        this.resetBreakAnims();
        this.resetBreakBarrier();
        this.resetCamera();
        this.resetCollMng();
        this.resetColliderLayer();
        this.resetCustomUpdateState();
        this.resetDynamicBarrier();
        this.resetEnemies();
        this.resetGold();
        this.resetGrade();
        this.resetLevelTimer();
        this.resetMap();
        this.resetParticle();
        this.resetPlayer();
        this.resetPortal();
        this.resetScanBox();
        this.resetSimpleComps();
        this.resetStaticBarrier();
        this.resetTrappers();
    }
    //#endregion

    //#region 关卡暂停/恢复
    protected isPaused: boolean;          //关卡是否暂停状态
    public get paused() { return this.isPaused; }
    protected pauseCount: number = 0;
    /**暂停关卡运行 */
    public pause(count: number = 1) {
        if (!this.paused) {
            //暂停动画播放
        }
        this.pauseCount += count;
        this.isPaused = true;
    }
    /**
     * 继续关卡运行
     * @param count 值为-1时强制恢复关卡运行
     */
    public resume(count: number = 1) {
        if (count === -1) {
            this.pauseCount = 0;
            this.isPaused = false;
        } else {
            this.pauseCount -= count;
            if (this.pauseCount <= 0) {
                this.pauseCount = 0;
                this.isPaused = false;
            }
        }
        if (!this.paused) {
            //恢复动画播放
        }

    }
    //#endregion

    /**************************************************对外功能**************************************************/
    //#region 进入关卡
    protected _enterLevel() {
        this.setData();
        this.camera.moveTo(0, cc.v3(0, 0, 0));
        this.playCameraEnterLevel();
    }

    protected setData() {
        //关卡内容
        let enemyPos = [];
        //地图
        let maps = this.levelData.data.maps;
        for (let i = 0; i < maps.length; ++i) {
            this.setMap(maps[i]);
        }
        this.setCollMngScope();
        //障碍物
        for (let i = 0; i < maps.length; ++i) {
            let p = maps[i].p;
            let mapData = GameData.getData(GlobalEnum.GameDataType.MapData, maps[i].n);
            this.setBreakBarrier(p, mapData.breakBarriers);
            this.setDynamicBarrier(p, mapData.dynamicBarriers);
            this.setStaticBarrier(p, mapData.staticBarriers);
            //敌人出现的坐标
            let arr = mapData.enemyPos;
            for (let index = 0, c = arr.length; index < c; ++index) {
                enemyPos.push({
                    x: p.x + arr[index].x,
                    y: p.y + arr[index].y,
                    z: p.z + arr[index].z,
                });
            }
        }
        this.enemyEnterPos = enemyPos;
        //传送门
        this.setPortals();
        //敌人
        let matchEnemies = GlobalData.get(GlobalEnum.myGlobalDataType.matchEnemies);
        this.setEnemies(matchEnemies);
        //玩家
        let playerWeaponSkin = PlayerData.getData("gameData.WeaponSkin");
        let playerWeapon = playerWeaponSkin.cur;
        if (playerWeaponSkin.try.type !== GlobalEnum.WeaponType.none && playerWeaponSkin.try.id !== 0) {
            playerWeapon = playerWeaponSkin.try;
        }
        this.setPlayer({
            p: this.getRandomEnemyPos(),
            skin: PlayerData.getCurSkinId(GlobalEnum.GameDataType.playerSkin),
            weaponType: playerWeapon.type,
            weaponId: playerWeapon.id,
            hat: PlayerData.getCurSkinId("HatSkin"),
        });
        //相机
        this.camera.setTarget(this.player.node);
        this.camera.enterLevel();
        this.canResurgence = true;
    }
    //#endregion

    //#region 进入教学模式
    protected _enterTeach() {
        this.setTeachData();
        this.camera.moveTo(0, cc.v3(0, 0, 0));
        this.camera.changeCamera({
            duration: 0,
            pos: cc.v3(0, 70, 15),
            angle: cc.v3(-80, 0, 0),
        });
        this.camera.moveTo(0.5, this.player.node.position);
        this.camera.resumeOriginalTransform(1, () => {
            this.startTeach();
        });
    }
    /**教学关卡数据 */
    protected setTeachData() {
        //关卡内容
        //地图
        let maps = this.levelData.data.maps;
        for (let i = 0; i < maps.length; ++i) {
            this.setMap(maps[i]);
        }
        this.setCollMngScope();
        //敌人坐标
        let enemyPos = [];
        for (let i = 0; i < maps.length; ++i) {
            let p = maps[i].p;
            let mapData = GameData.getData(GlobalEnum.GameDataType.MapData, maps[i].n);
            //敌人出现的坐标
            let arr = mapData.enemyPos;
            for (let index = 0, c = arr.length; index < c; ++index) {
                enemyPos.push({
                    x: p.x + arr[index].x,
                    y: p.y + arr[index].y,
                    z: p.z + arr[index].z,
                });
            }
        }
        this.enemyEnterPos = enemyPos;
        //传送门
        // this.setPortals();
        //敌人
        let matchEnemies = GlobalData.get(GlobalEnum.myGlobalDataType.matchEnemies);
        this.setEnemies(matchEnemies);
        //玩家
        let playerWeaponSkin = PlayerData.getData("gameData.WeaponSkin");
        let playerWeapon = playerWeaponSkin.cur;
        if (playerWeaponSkin.try.type !== GlobalEnum.WeaponType.none && playerWeaponSkin.try.id !== 0) {
            playerWeapon = playerWeaponSkin.try;
        }
        this.setPlayer({
            p: cc.v3(6, 0, 13),
            skin: PlayerData.getCurSkinId(GlobalEnum.GameDataType.playerSkin),
            weaponType: playerWeapon.type,
            weaponId: playerWeapon.id,
        });
        //相机
        this.camera.setTarget(this.player.node);
        this.camera.enterLevel();
        this.canResurgence = true;
    }
    protected onAddPortal() {
        this.setPortals();
    }
    //#endregion

    //#region 进入首页
    /**设置在首页中作为背景时需要显示的内容 */
    protected setEnterLobbyData() {
    }
    //#endregion

    /**************************************************管理数据**************************************************/
    /**敌人出现的位置 */
    protected enemyEnterPos: cc.Vec3[] = [];

    //#region 玩家成绩
    /**玩家成绩 */
    protected grade: {
        /**拾取的金币 */
        gold: number,
        /**击杀的敌人 */
        killed: number,
    } = null;
    protected allRoleRank: { id: number, score: number }[] = [];
    protected initGrade() {
        this.grade = {
            gold: 0,
            killed: 0,
        };
        this.allRoleRank = [];
    }
    protected resetGrade() {
        this.grade.gold = 0;
        this.grade.killed = 0;
        this.allRoleRank = [];
    }
    protected recordRoleRank() {
        this.allRoleRank.push({
            id: this.player.Id,
            score: 0,
        });
        for (let i = this.allEnemies.length - 1; i >= 0; --i) {
            this.allRoleRank.push({
                id: this.allEnemies[i].Id,
                score: 0,
            });
        }
    }
    protected addGradeGold() {
        this.grade.gold += 1;
        this.emit(EventType.LevelEvent.updateGold, this.grade.gold);
    }
    protected addGradeKilled() {
        this.grade.killed += 1;
        // if (this.grade.killed == 2) {
        //     this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.killDouble);
        // } else if (this.grade.killed == 3) {
        //     this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.killMulti);
        // } else if (this.grade.killed > 3) {
        //     this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.killUltra);
        // }
        this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.killed);
    }
    protected getResultData() {
        return {
            lv: this.levelData.lv,
            gold: this.grade.gold + 100,
        };
    }

    //#endregion


    /**************************************************管理对象**************************************************/
    //#region 玩家
    @property(cc.Node)
    protected playerLayer: cc.Node = null;
    protected player: Player = null;
    protected playerDeadBody: cc.Node = null;
    protected initPlayer() {
    }
    protected resetPlayer() {
        if (!!this.player) {
            GlobalPool.put(this.player.node);
            this.player = null;
            GlobalData.set(GlobalEnum.myGlobalDataType.player, null);
        }
        if (!!this.playerDeadBody) {
            GlobalPool.put(this.playerDeadBody);
            this.playerDeadBody = null;
        }
    }
    protected setPlayer(data) {
        this.resetPlayer();
        let node = GlobalPool.get("Player", data);
        this.player = node[customPoolScript];
        this.playerLayer.addChild(node);
        this.player.setEulerAngles(-90);
        this.player.enableRigidNode();
        this.player.enterLevel();
        GlobalData.set(GlobalEnum.myGlobalDataType.player, this.player);
    }
    protected updatePlayer(dt: number) {
        this.player.customUpdate(dt);
    }
    //#endregion

    //#region 相机
    @property(LevelCamera)
    protected camera: LevelCamera = null;
    protected initCamera() {
        this.camera.init();
        GlobalData.set(GlobalEnum.Common.GlobalDataType.levelCamera, this.camera);
    }
    protected resetCamera() {
        this.camera.reset();
    }
    protected updateCamera(dt: number) {
        this.camera.customUpdate(dt);
    }
    protected playCameraEnterLevel() {
        this.camera.changeCamera({
            duration: 0,
            pos: cc.v3(0, 70, 15),
            angle: cc.v3(-80, 0, 0),
        });
        this.camera.moveTo(0.5, this.player.node.position);
        this.camera.resumeOriginalTransform(1, () => {
            this.startLevel();
            this.emit(EventType.LevelEvent.showHandAnim);
            setTimeout(() => {
                this.showUI(GlobalEnum.UI.trySkin);
                this.enterCustomUpdateState(GlobalEnum.LevelState.waitTrySkin);
            }, 1000);
        });
    }
    //#endregion

    //#region 地图
    @property(cc.Node)
    protected mapLayer: cc.Node = null;
    /**地图范围 */
    protected mapScope: {
        xMin: number,
        xMax: number,
        zMin: number,
        zMax: number,
    };
    protected initMap() {
    }
    protected resetMap() {
        this.mapScope = null;
        this.removeMap();
    }
    protected removeMap() {
        GlobalPool.putAllChildren(this.mapLayer);
    }
    protected setMap(data: { n: string, p: cc.Vec3 }) {
        let map = GlobalPool.get(data.n);
        this.mapLayer.addChild(map);
        map.setPosition(data.p);
        map[customPoolScript].enableRigidNode();
        let mapData = GameData.getData(GlobalEnum.GameDataType.MapData, data.n);
        let scope = mapData.scope;
        let xMin = scope.xMin + data.p.x;
        let xMax = scope.xMax + data.p.x;
        let zMin = scope.zMin + data.p.z;
        let zMax = scope.zMax + data.p.z;
        if (!this.mapScope) {
            this.mapScope = {
                xMin: xMin,
                xMax: xMax,
                zMin: zMin,
                zMax: zMax,
            };
        } else {
            if (this.mapScope.xMin > xMin) {
                this.mapScope.xMin = xMin;
            }
            if (this.mapScope.xMax < xMax) {
                this.mapScope.xMax = xMax;
            }
            if (this.mapScope.zMin > zMin) {
                this.mapScope.zMin = zMin;
            }
            if (this.mapScope.zMax < zMax) {
                this.mapScope.zMax = zMax;
            }
        }
    }
    protected getRandomEnemyPos() {
        //随机出现位置
        let index = Math.round(Math.random() * (this.enemyEnterPos.length - 1));
        let p = this.enemyEnterPos[index];
        if (this.enemyEnterPos.length > 1) {
            this.enemyEnterPos.splice(index, 1);
        }
        return p;
    }
    //#endregion

    //#region 传送门
    @property(cc.Node)
    protected portalLayer: cc.Node = null;
    protected allPortals: Portal[] = [];
    protected initPortal() {
        this.allPortals = [];
    }
    protected resetPortal() {
        GlobalPool.putAllChildren(this.portalLayer, true);
        this.allPortals = [];
    }
    protected setPortals() {
        let maps = this.levelData.data.maps;
        if (maps.length == 1) return;
        for (let i = maps.length - 1; i >= 0; --i) {
            let mapData = GameData.getData(GlobalEnum.GameDataType.MapData, maps[i].n);
            let p = maps[i].p;
            for (let j = mapData.portalPos.length - 1; j >= 0; --j) {
                this.addPortal(p, mapData.portalPos[j]);
            }
        }
        //关联传送门
        let maxIndex = maps.length - 1;
        for (let i = 0; i < maxIndex; ++i) {
            this.allPortals[i * 2].nextDoor = this.allPortals[i * 2 + 3];
            this.allPortals[i * 2 + 3].nextDoor = this.allPortals[i * 2];
        }
        this.allPortals[maxIndex * 2].nextDoor = this.allPortals[1];
        this.allPortals[1].nextDoor = this.allPortals[maxIndex * 2];
        GlobalData.set(GlobalEnum.myGlobalDataType.portals, this.allPortals);
    }
    protected addPortal(offset: cc.Vec3, pos: cc.Vec3) {
        let node = GlobalPool.get("Portal");
        this.portalLayer.addChild(node);
        this.allPortals.push(node[customPoolScript]);
        node.setPosition(cc.v3(offset.x + pos.x, 0, offset.z + pos.z));
    }
    protected updatePortal(dt: number) {
        this.runCustomUpdate(this.allPortals, dt);
    }
    protected checkPortal() {
        for (let i = this.allPortals.length - 1; i >= 0; --i) {
            if (!this.allPortals[i].visible || !this.allPortals[i].nextDoor.visible) {
                continue;
            }
            let portal = this.allPortals[i];
            if (this.player.isAlive && portal.checkCollRole(this.player)) {
                portal.chuanSongRole(this.player);
                portal.nextDoor.chuanSongRole(this.player);
                this.player.jumpInPortal(portal.node.position, portal.nextDoor.node.getPosition());
                continue;
            }
            for (let j = this.allEnemies.length - 1; j >= 0; --j) {
                if (this.allEnemies[j].isAlive && portal.checkCollRole(this.allEnemies[j])) {
                    portal.chuanSongRole(this.allEnemies[j]);
                    portal.nextDoor.chuanSongRole(this.allEnemies[j]);
                    this.allEnemies[j].jumpInPortal(portal.node.position, portal.nextDoor.node.getPosition());
                    break;
                }
            }
        }
    }
    //#endregion

    //#region 静态障碍物
    @property(cc.Node)
    protected staticBarrierLayer: cc.Node = null;
    protected initStaticBarrier() {

    }
    protected resetStaticBarrier() {
        GlobalPool.putAllChildren(this.staticBarrierLayer);
    }
    protected setStaticBarrier(offset: cc.Vec3, data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            this.addStaticBarrier(offset, data[i]);
        }
    }
    protected addStaticBarrier(offset: cc.Vec3, data) {
        let node = GlobalPool.get(data.n, data);
        this.staticBarrierLayer.addChild(node);
        let js = node[customPoolScript];
        if (!!js) {
            js.setPosition(cc.v3(data.p.x + offset.x, data.p.y + offset.y, data.p.z + offset.z));
            js.enableRigidNode();
        } else {
            node.setPosition(data.p.x + offset.x, data.p.y + offset.y, data.p.z + offset.z);
        }
    }
    //#endregion

    //#region 可撞开障碍物
    @property(cc.Node)
    protected dynamicBarrierLayer: cc.Node = null;
    protected dynamicBarriers: LevelColler[] = [];
    protected initDynamicBarrier() {
        this.dynamicBarriers = [];
    }
    protected resetDynamicBarrier() {
        GlobalPool.putAllChildren(this.dynamicBarrierLayer);
        this.dynamicBarriers = [];
    }
    protected setDynamicBarrier(offset: cc.Vec3, data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            this.addDynamicBarrier(offset, data[i]);
        }
    }
    protected addDynamicBarrier(offset: cc.Vec3, data) {
        let node = GlobalPool.get(data.n, data);
        this.dynamicBarrierLayer.addChild(node);
        let js = node[customPoolScript];
        if (!!js) {
            this.dynamicBarriers.push(js);
            js.setPosition(cc.v3(data.p.x + offset.x, data.p.y + offset.y, data.p.z + offset.z));
            js.enableRigidNode();
        } else {
            node.setPosition(data.p.x + offset.x, data.p.y + offset.y, data.p.z + offset.z);
        }
    }
    protected removeDynamicBarrier(barrier) {
        this.removeElementInArray(barrier, this.dynamicBarriers);
        GlobalPool.put(barrier.node);
        CollerManager.removeObj(barrier, GlobalEnum.CollerType.barrier);
    }
    protected updateDynamicBarrier(dt: number) {
        this.runCustomUpdate(this.dynamicBarriers, dt);
    }
    //#endregion

    //#region 可破坏障碍物
    @property(cc.Node)
    protected breakBarrierLayer: cc.Node = null;
    protected initBreakBarrier() {

    }
    protected resetBreakBarrier() {
        GlobalPool.putAllChildren(this.breakBarrierLayer);
    }
    protected setBreakBarrier(offset, data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            this.addBreakBarrier(offset, data[i]);
        }
    }
    protected addBreakBarrier(offset: cc.Vec3, data) {
        // if (data.n != "TREE__cv16huang") return;
        let node = GlobalPool.get(data.n, data);
        this.breakBarrierLayer.addChild(node);
        if (!!node[customPoolScript]) {
            node[customPoolScript].setPosition(cc.v3(data.p.x + offset.x, data.p.y + offset.y, data.p.z + offset.z));
            node[customPoolScript].enableRigidNode();
            CollerManager.addObj(node[customPoolScript], GlobalEnum.CollerType.barrier);
        } else {
            node.setPosition(data.p.x + offset.x, data.p.y + offset.y, data.p.z + offset.z);
        }
    }
    protected removeBreakBarrier(barrier) {
        GlobalPool.put(barrier.node);
        CollerManager.removeObj(barrier, GlobalEnum.CollerType.barrier);
    }
    //#endregion

    //#region 障碍物碎片特效层
    @property(cc.Node)
    protected breakAnimLayer: cc.Node = null;
    protected breakAnims = [];
    protected initBreakAnims() {
        this.breakAnims = [];
    }
    protected resetBreakAnims() {
        GlobalPool.putAllChildren(this.breakAnimLayer);
        this.breakAnims = [];
    }
    protected addBreakAnim(data) {
        let node = GlobalPool.get(data.breakEffectName);
        if (!node) return;
        this.breakAnimLayer.addChild(node);
        this.breakAnims.push(node[customPoolScript]);
        let e = Math.random() * 360;
        node.eulerAngles = cc.v3(0, e, 0);
        node.setPosition(data.p);
        node[customPoolScript].play();
    }
    protected removeBreakAnim(js) {
        GlobalPool.put(js.node);
        this.removeElementInArray(js, this.breakAnims);
    }
    protected updateBreakAnims(dt: number) {
        this.runCustomUpdate(this.breakAnims, dt);
    }
    //#endregion

    //#region 金币层
    @property(cc.Node)
    protected goldLayer: cc.Node = null;
    protected allGolds: LevelColler[] = [];
    protected initGold() {
        this.allGolds = [];
    }
    protected resetGold() {
        GlobalPool.putAllChildren(this.goldLayer, true);
        this.allGolds = [];
    }
    protected addGold(data: { p: cc.Vec3, speed: cc.Vec3 }) {
        let node = GlobalPool.get("GoldItem", data);
        this.goldLayer.addChild(node);
        let js = node[customPoolScript];
        js.enterLevel(data.speed);
        this.allGolds.push(js);
    }
    protected removeGold(gold: LevelColler) {
        this.removeElementInArray(gold, this.allGolds);
        GlobalPool.put(gold.node);
        CollerManager.removeObj(gold, GlobalEnum.CollerType.props);
    }
    protected updateGold(dt: number) {
        GoldItem.radian += dt;
        GoldItem.sinY = Math.sin(GoldItem.radian);
        GoldItem.cosY = Math.cos(GoldItem.radian);
        this.runCustomUpdate(this.allGolds, dt);
    }
    //#endregion

    //#region 血液特效层

    //#endregion

    //#region 尸体层
    @property(cc.Node)
    protected bodyLayer: cc.Node = null;
    protected allDeadBodies: yyComponent[] = [];
    protected initBodyLayer() {
        this.allDeadBodies = [];
    }
    protected resetBodyLayer() {
        GlobalPool.putAllChildren(this.bodyLayer, true);
        this.allDeadBodies = [];
    }
    protected addDeadAnim(data: { p: cc.Vec3, radian: number, scale: number, isPlayer?: boolean, skin: number, anim?: string }): cc.Node {
        // let str = !!data.anim ? data.anim : "RoleDeadAnim";
        let str = !!data.anim ? data.anim : "RoleDeadAnim2";
        let node = GlobalPool.get(str);
        this.bodyLayer.addChild(node);
        if (!node[customPoolScript]) {
            console.log(node);
        }
        node[customPoolScript].play(data);
        this.allDeadBodies.push(node[customPoolScript]);
        return node;
    }
    protected removeDeadAnim(js) {
        this.removeElementInArray(js, this.allDeadBodies);
    }
    protected updateDeadAnim(dt: number) {
        this.runCustomUpdate(this.allDeadBodies, dt);
    }
    //#endregion

    //#region 敌人（AI）角色层 
    @property(cc.Node)
    protected roleLayer: cc.Node = null;
    protected allEnemies: Enemy[] = [];
    protected initEnemies() {
        this.allEnemies = [];
        AIManager.init();
    }
    protected resetEnemies() {
        AIManager.reset();
        GlobalPool.putAllChildren(this.roleLayer, true);
        this.allEnemies = [];
        GlobalData.set(GlobalEnum.myGlobalDataType.enemies, this.allEnemies);
    }
    protected setEnemies(data) {
        let count = data.length;
        if (count >= this.enemyEnterPos.length) {
            count = this.enemyEnterPos.length - 1;
        }
        for (let i = 0; i < count; ++i) {
            this.addEnemy(data[i]);
        }
        GlobalData.set(GlobalEnum.myGlobalDataType.enemies, this.allEnemies);
    }
    protected addEnemy(data) {
        let node = GlobalPool.get("Enemy", data);
        this.roleLayer.addChild(node);
        let enemy = node[customPoolScript];
        if (undefined !== data.e) {
            enemy.setEulerAngles(data.e);
        } else {
            let e = Math.random() * 360;
            enemy.setEulerAngles(e);
        }
        //随机出现位置
        if (undefined !== data.p) {
            enemy.setPosition(data.p);
        } else {
            let p = this.getRandomEnemyPos();
            enemy.setPosition(p);
        }
        enemy.enableRigidNode();
        this.allEnemies.push(enemy);
        if (undefined !== data.invicible) {
            enemy.enterLevel({ invicible: data.invicible });
        } else {
            enemy.enterLevel();
        }
        AIManager.addEnemy(enemy);
    }
    protected removeEnemy(enemy: Enemy) {
        AIManager.removeEnemy(enemy);
        GlobalPool.put(enemy.node);
        this.removeElementInArray(enemy, this.allEnemies);
    }
    protected updateEnemies(dt: number) {
        AIManager.customUpdate(dt);
        this.runCustomUpdate(this.allEnemies, dt);
    }
    //#endregion

    //#region 无敌特效层
    @property(cc.Node)
    protected scanBoxLayer: cc.Node = null;
    protected initScanBox() {

    }
    protected resetScanBox() {
        GlobalPool.putAllChildren(this.scanBoxLayer, true);
    }
    protected addScanBox(node: cc.Node) {
        this.scanBoxLayer.addChild(node);
    }
    //#endregion

    //#region 爆炸特效层
    @property(cc.Node)
    protected boomLayer: cc.Node = null;
    protected initBoom() {

    }
    protected resetBoom() {
        GlobalPool.putAllChildren(this.boomLayer);
    }
    protected addBoom(data: { p: cc.Vec3, s: number }) {
        let node = GlobalPool.get("Boom");
        node.setPosition(data.p);
        this.boomLayer.addChild(node);
        node[customPoolScript].play(data.s);
    }
    //#endregion

    //#region 粒子特效层
    @property(cc.Node)
    protected particleLayer: cc.Node = null;
    protected initParticle() {

    }
    protected resetParticle() {
        GlobalPool.putAllChildren(this.particleLayer);
    }
    protected addParticle(data: { n: string, p: cc.Vec3, s?: number, radian?: number }) {
        let node = GlobalPool.get(data.n);
        if (!node) { return; }
        this.particleLayer.addChild(node);
        if (undefined !== data.s) {
            node.setScale(data.s, data.s, data.s);
        } else {
            node.setScale(1, 1, 1);
        }
        if (undefined !== data.radian) {
            let r = data.radian * 0.5;
            node.setRotation(0, Math.sin(r), 0, Math.cos(r));
        } else {
            node.setRotation(0, 0, 0, 1);
        }
        node[customPoolScript].play();
        node.setPosition(data.p);
    }
    //#endregion

    //#region 其他特效层

    //#endregion

    //#region 2D物理引擎世界
    protected colliderLayer: cc.Node = null;
    protected initColliderLayer() {
        this.colliderLayer = GlobalData.get(GlobalEnum.myGlobalDataType.colliderLayer);
    }
    protected resetColliderLayer() {

    }
    /**同步2D节点信息到3D节点 */
    protected sync2to3() {
        let fun = "syncRigidToModel";
        this.runSyncFun(fun);
    }
    /**同步3D节点信息到2D节点 */
    protected sync3to2() {
        let fun = "syncModelToRigid";
        this.runSyncFun(fun);
    }
    /**
     * 执行同步方法
     * @param fun   方法名
     */
    protected runSyncFun(fun: string) {
        //玩家
        this.player[fun]();
        //敌人
        for (let i = this.allEnemies.length - 1; i >= 0; --i) {
            this.allEnemies[i][fun]();
        }
        //可撞开障碍物
        for (let i = this.dynamicBarriers.length - 1; i >= 0; --i) {
            this.dynamicBarriers[i][fun]();
        }
        //金币
        for (let i = this.allGolds.length - 1; i >= 0; --i) {
            this.allGolds[i][fun]();
        }

    }
    //#endregion

    //#region 攻击框
    protected allAtkBox: AtkBox[] = [];
    protected initAtkBox() {
        this.allAtkBox = [];
    }
    protected resetAtkBox() {
        this.allAtkBox = [];
    }
    protected addAtkBox(box: AtkBox) {
        let index = this.allAtkBox.indexOf(box);
        if (index < 0) {
            this.allAtkBox.push(box);
        }
    }
    protected removeAtkBox(box: AtkBox) {
        let index = this.allAtkBox.indexOf(box);
        if (index >= 0) {
            this.allAtkBox.splice(index, 1);
        }
    }
    protected checkAtkBox() {
        for (let i = this.allAtkBox.length - 1; i >= 0; --i) {
            if (!this.allAtkBox[i] || !this.allAtkBox[i].visible) {
                continue;
            }
            let box = this.allAtkBox[i];
            CollerManager.checkColl(box, GlobalEnum.CollerType.barrier);
            let enemies = this.allEnemies;
            for (let i = enemies.length - 1; i >= 0; --i) {
                if (box.checkAABB(enemies[i])) {
                    box.onColled(enemies[i]);
                }
            }
            let barriers = this.dynamicBarriers;
            for (let i = barriers.length - 1; i >= 0; --i) {
                if (box.checkAABB(barriers[i])) {
                    box.onColled(barriers[i]);
                }
            }
            if (box.checkAABB(this.player)) {
                box.onColled(this.player);
            }
            box.processHitAudio();
        }
    }
    //#endregion

    //#region 炸弹攻击框
    @property(cc.Node)
    protected trapperLayer: cc.Node = null;
    protected allTrappers: Trapper[] = [];
    protected initTrappers() {
        this.allTrappers = [];
    }
    protected resetTrappers() {
        GlobalPool.putAllChildren(this.trapperLayer);
        this.allTrappers = [];
    }
    protected addTrapper(data: { role: Role, speed: cc.Vec3 }) {
        let str = "trapper" + data.role.weaponId;
        str += !!data.role.isPlayer ? "player" : "enemy";
        let node = GlobalPool.get(str, data);
        this.trapperLayer.addChild(node);
        this.allTrappers.push(node[customPoolScript]);
    }
    protected removeTrapper(js) {
        GlobalPool.put(js.node);
        this.removeElementInArray(js, this.allTrappers);
    }
    protected updateTrapper(dt: number) {
        this.runCustomUpdate(this.allTrappers, dt);
    }
    protected checkTrapperColl() {
        for (let i = this.allTrappers.length - 1; i >= 0; --i) {
            if (!this.allTrappers[i] || !this.allTrappers[i].visible) {
                continue;
            }
            let trapper = this.allTrappers[i];
            //可破坏障碍物
            CollerManager.checkColl(trapper, GlobalEnum.CollerType.barrier);
            //敌人
            let enemies = this.allEnemies;
            for (let i = enemies.length - 1; i >= 0; --i) {
                if (trapper.checkAABB(enemies[i].getAABB())) {
                    trapper.onColled(enemies[i]);
                }
            }
            //动态障碍物
            let barriers = this.dynamicBarriers;
            for (let i = barriers.length - 1; i >= 0; --i) {
                if (trapper.checkAABB(barriers[i].getAABB())) {
                    trapper.onColled(barriers[i]);
                }
            }
            if (trapper.checkAABB(this.player.getAABB())) {
                trapper.onColled(this.player);
            }
            trapper.processHitAudio();
            if (!trapper.visible) {
                GlobalPool.put(trapper.node);
                this.allTrappers.splice(i, 1);
            }
        }
    }
    //#endregion

    //#region 八叉树碰撞检测管理器
    protected initCollMng() {
        CollerManager.init();
    }
    protected resetCollMng() {
        CollerManager.reset();
    }
    protected setCollMngScope() {
        CollerManager.setTreeScope(this.mapScope.xMin, this.mapScope.xMax, this.mapScope.zMin, this.mapScope.zMax);
    }
    protected updateCollMng(dt: number) {
        //玩家与金币
        CollerManager.checkColl(this.player, GlobalEnum.CollerType.props);
        //敌人与金币
        for (let i = this.allEnemies.length - 1; i >= 0; --i) {
            CollerManager.checkColl(this.allEnemies[i], GlobalEnum.CollerType.props);
        }
    }
    //#endregion

    /**************************************************流程**************************************************/
    protected stepWaitTrySkin(dt: number) {

    }
    protected stepLevelPlaying(dt: number) {
        AIManager.enterLevel();
        this.enterCustomUpdateState(GlobalEnum.LevelState.fighting);
    }

    //#region 战斗中
    protected stepPlayerFighting(dt: number) {
        this.sync2to3();

        this.updateBreakAnims(dt);
        this.updateCollMng(dt);
        this.updateDeadAnim(dt);
        this.updateDynamicBarrier(dt);
        this.updateEnemies(dt);
        this.updateGold(dt);
        this.updatePlayer(dt);
        this.updateCamera(dt);
        this.updateTrapper(dt);
        this.updatePortal(dt);
        this.checkPortal();
        this.sync3to2();
        this.checkAtkBox();
        this.checkTrapperColl();
    }
    //#endregion

    //#region 新手教学流程
    protected stepTeaching(dt: number) {
        this.sync2to3();

        this.updateBreakAnims(dt);
        this.updateCollMng(dt);
        this.updateDeadAnim(dt);
        this.updateDynamicBarrier(dt);
        // this.updateEnemies(dt);
        this.updateGold(dt);
        this.updatePlayer(dt);
        this.updateCamera(dt);
        this.updateTrapper(dt);
        this.updatePortal(dt);
        this.checkPortal();
        this.sync3to2();
        this.checkAtkBox();
        this.checkTrapperColl();
    }
    //#endregion

    //#region 胜利
    protected stepLevelWin(dt: number) {
        this.sync2to3();

        this.updateBreakAnims(dt);
        // this.updateCollMng(dt);
        this.updateDeadAnim(dt);
        this.updateDynamicBarrier(dt);
        // this.updateEnemies(dt);
        this.updateGold(dt);
        // this.updatePlayer(dt);
        // this.updateCamera(dt);
        // this.updateWeaponStreak(dt);
        this.updatePortal(dt);
        this.updateTrapper(dt);
        this.sync3to2();
        // this.checkAtkBox();
    }
    //#endregion

    //#region 失败
    protected stepLevelLose(dt: number) {
        this.sync2to3();

        this.updateBreakAnims(dt);
        // this.updateCollMng(dt);
        this.updateDeadAnim(dt);
        this.updateDynamicBarrier(dt);
        this.updateEnemies(dt);
        this.updateGold(dt);
        // this.updatePlayer(dt);
        // this.updateCamera(dt);
        // this.updateWeaponStreak(dt);
        this.updatePortal(dt);
        this.updateTrapper(dt);
        this.sync3to2();
        this.checkAtkBox();
    }
    //#endregion

    //#region 状态：首页中
    protected stepLobby(dt: number) {
        // this.updateCamera(dt);
    }
    //#endregion

    /**************************************************事件**************************************************/
    protected onTestWin() {
        this.win();
    }
    protected onTestLose() {
        this.lose();
    }

    protected playerScale: number = 1;
    protected playerDeadPosition: cc.Vec3;
    /**玩家死亡 */
    protected onPlayerDead(data) {
        this.playerScale = this.player.roleScale;
        this.playerDeadPosition = this.player.node.getPosition();
        this.emit(EventType.Common.AudioEvent.stopBGM);
        this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.lose);
        //禁用触摸操作，等玩家死亡动画结束后再显示UI
        this.emit(EventType.Common.CtrlEvent.ctrlEnd);
        this.enterCustomUpdateState(GlobalEnum.LevelState.lose);
        //播放玩家死亡动画
        this.playerDeadBody = this.addDeadAnim(data);
        // this.lose();
        setTimeout(() => {
            let loseData = {
                canResurgence: this.canResurgence,
                lv: this.levelData.lv,
                gold: this.grade.gold,
            };
            this.canResurgence = false;
            this.lose(loseData);
        }, 300);
    }

    protected canResurgence: boolean = true;
    /**玩家死亡动画结束 */
    protected onPlayerDeadAnimFinished() {
        // let data = {
        //     canResurgence: this.canResurgence,
        //     lv: this.levelData.lv,
        //     gold: this.grade.gold,
        // };
        // this.canResurgence = false;
        // this.lose(data);
        // this.emit(EventType.LevelEvent.playLoseAnim);
    }

    /**复活 */
    protected onResurgence() {
        this.emit(EventType.Common.AudioEvent.playBGM, GlobalEnum.AudioClip.BGM, true);
        GlobalPool.put(this.playerDeadBody);
        this.playerDeadBody = null;
        this.player.setRoleScale(this.playerScale);
        this.player.resurgence(this.playerDeadPosition);
        this.emit(EventType.Common.CtrlEvent.ctrlStart);
        this.enterCustomUpdateState(GlobalEnum.LevelState.playing);
    }

    /**UI胜利动画结束 */
    protected onWinAnimFinish() {
        this.win(this.getResultData());
    }
    /**UI失败动画结束 */
    protected onLoseAnimFinish() {
        this.lose();
    }

    //#region 2D刚体节点
    protected onAddRigidNode(node: cc.Node) {
        this.colliderLayer.addChild(node);
        node.layer = this.colliderLayer.layer;
    }

    //#endregion

    //#region 障碍物
    protected onRemoveDynamicBarrier(barrier) {
        this.removeDynamicBarrier(barrier);
    }
    protected onRemoveBreakBarrier(barrier) {
        this.removeBreakBarrier(barrier);
    }
    protected onAddBreakAnim(data) {
        this.addBreakAnim(data);
    }
    protected onRemoveBreakAnim(js) {
        this.removeBreakAnim(js);
    }
    //#endregion

    //#region 金币
    protected onDropGold(data: { p: cc.Vec3, count: number }) {
        //掉落8个金币
        let s = cc.v3();
        let pos = cc.v3();
        pos.x = data.p.x;
        pos.y = 1;
        pos.z = data.p.z;
        let v = 0.08;
        for (let i = 0, step = 6.28 / data.count; i < 6.28; i += step) {
            s.x = Math.cos(i) * v;
            s.y = 12;
            s.z = Math.sin(i) * v;
            this.addGold({ p: pos, speed: s });
        }
    }
    protected onAddGoldColler(gold: LevelColler) {
        CollerManager.addObj(gold, GlobalEnum.CollerType.props);
    }
    protected onGetGold() {
        this.addGradeGold();
    }
    protected onRemoveGold(gold) {
        this.removeGold(gold);
    }
    //#endregion

    //#region 攻击框
    protected onAddAtkBox(box: AtkBox) {
        this.addAtkBox(box);
    }
    protected onRemoveAtkBox(box: AtkBox) {
        this.removeAtkBox(box);
    }
    //#endregion

    //#region 敌人
    protected onPlayerKillEnemy() {
        this.addGradeKilled();
    }
    protected onEnemyDead(enemy: Enemy) {
        this.removeEnemy(enemy);
        this.emit(EventType.LevelEvent.updateRemainEnemy, this.allEnemies.length);
        //检测胜负
        if (!!this.player && this.allEnemies.length == 0) {
            this.emit(EventType.Common.CtrlEvent.ctrlEnd);
            this.emit(EventType.Common.AudioEvent.stopBGM);
            setTimeout(() => {
                this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.win);
            }, 500);
            this.player.playWinAnim();
            this.enterCustomUpdateState(GlobalEnum.LevelState.win);
            this.camera.changeCamera({
                duration: 1,
                pos: cc.v3(0, 2.7, 5.6),
                angle: cc.v3(-20, 0, 0),
                cb: () => {
                    // this.win(this.getResultData());
                    // this.scheduleOnce(() => {
                    //     this.win(this.getResultData());
                    // }, 1);
                }
            });
            this.scheduleOnce(() => {
                this.win(this.getResultData());
            }, 0.3);
        }
    }
    //#endregion

    //#region 尸体
    protected onAddDeadBody(data: { atkRolePos: cc.Vec3, weaponType: GlobalEnum.WeaponType, p: cc.Vec3, mat: cc.Material, scale: number, radian: number, isPlayer?: boolean, skin: number, anim?: string }) {
        this.addDeadAnim(data);
    }
    protected onDeadAnimFinish(js) {
        this.removeDeadAnim(js);
    }
    //#endregion

    //#region 无敌特效
    protected onAddScanBox(node) {
        this.addScanBox(node);
    }
    //#endregion

    //#region 粒子特效
    protected onAddParticle(data: { n: string, p: cc.Vec3, s?: number }) {
        this.addParticle(data);
    }
    //#endregion

    //#region 皮肤试用
    protected onDecideSkin() {
        let playerWeaponSkin = PlayerData.getData("gameData.WeaponSkin");
        let playerWeapon = playerWeaponSkin.cur;
        if (playerWeaponSkin.try.type !== GlobalEnum.WeaponType.none && playerWeaponSkin.try.id !== 0) {
            playerWeapon = playerWeaponSkin.try;
        }
        let skin = PlayerData.getCurSkinId("PlayerSkin");
        this.player.changeSkin({
            weaponType: playerWeapon.type,
            weaponId: playerWeapon.id,
            skin: skin,
        });

        this.enterCustomUpdateState(GlobalEnum.LevelState.fighting);
    }
    protected onChangePlayerSkin() {
        let playerWeaponSkin = PlayerData.getData("gameData.WeaponSkin");
        let playerWeapon = playerWeaponSkin.cur;
        if (playerWeaponSkin.try.type !== GlobalEnum.WeaponType.none && playerWeaponSkin.try.id !== 0) {
            playerWeapon = playerWeaponSkin.try;
        }
        this.player.changeSkin({
            weaponType: playerWeapon.type,
            weaponId: playerWeapon.id,
        });
    }

    //#endregion

}
